//
//  HomeViewController.m
//  RuntimeDemo
//
//  Created by 张敬 on 2019/10/14.
//  Copyright © 2019年 xiuxiu. All rights reserved.
//

#import "HomeViewController.h"
#import "UIView+Category.h"
#import <objc/runtime.h>

@interface Man : NSObject

@end

@implementation Man

- (void)test{
    NSLog(@"_____________  test_002");
}

@end

@interface HomeViewController ()<UITableViewDelegate>

@property (nonatomic, copy) NSString *name;

@end

@implementation HomeViewController


- (void)viewDidLoad {
    
    NSLog(@"系统的方法");
    [super viewDidLoad];
    //[self logInfo];
    //[self addMethods];
    //[self addPropertys];
}


//黑魔法替换方法
+ (void)load{
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        
        Class class = [self class];
        
        SEL originalSelector = @selector(viewDidLoad);
        SEL swizzledSelector = @selector(sfs_viewDidLoad);
        
        Method originalMethod = class_getInstanceMethod(class, originalSelector);
        Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
        
        BOOL didAddMethod = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
        if (didAddMethod) {
            class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
        }else{
            method_exchangeImplementations(originalMethod, swizzledMethod);
        }
    });
}


- (void)sfs_viewDidLoad{
    
    NSLog(@"交换的方法");
    [self sfs_viewDidLoad];
}


/*给类别添加属性*/
- (void)addPropertys{
    
    UIView *bg = [[UIView alloc] init];
    bg.backgroundColor = [UIColor redColor];
    bg.frame = CGRectMake(10, 100, 100, 100);
    bg.isNeedAnimation = YES;
    bg.tapBlock = ^{
        NSLog(@"点击了我");
    };
    
    bg.defaultColor = [UIColor greenColor];
    [self.view addSubview:bg];
}

/*添加动态解析方法*/
- (void)addMethods{
   
    UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
    btn.frame = CGRectMake(10, 100, 100, 30);
    btn.backgroundColor = [UIColor redColor];
    [btn addTarget:self action:@selector(test) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:btn];
}

+ (BOOL)resolveInstanceMethod:(SEL)sel{
    
//    if ([NSStringFromSelector(sel) isEqualToString:@"test"]) {
//        class_addMethod(self, sel,(IMP)runMethods , "v@:*");
//    }
    return [super resolveInstanceMethod:sel];
}

void runMethods(id self , SEL _cmb,  NSString *string){
    NSLog(@"_______________ Test_001");
}

- (id)forwardingTargetForSelector:(SEL)aSelector{
    
//    if ([NSStringFromSelector(aSelector) isEqualToString:@"test"]) {
//        return [Man new];
//    }
    return [super forwardingTargetForSelector:aSelector];
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
    if ([NSStringFromSelector(aSelector) isEqualToString:@"test"]) {
        return [NSMethodSignature signatureWithObjCTypes:"v@:"];
    }
    return [super methodSignatureForSelector:aSelector];
}


- (void)forwardInvocation:(NSInvocation *)anInvocation{
    
    SEL sel = anInvocation.selector;
    Man *man = [[Man alloc] init];
    
    if ([man respondsToSelector:sel]) {
        [anInvocation invokeWithTarget:man];
    }else{
        [self doesNotRecognizeSelector:sel];
    }
    
}

- (void)doesNotRecognizeSelector:(SEL)aSelector{
    NSLog(@"_________________ test_003");
}


/*动态的查看类的属性/方法/成员变量/协议列表*/
- (void)logInfo{
    
    unsigned int count;
    
    //属性
    objc_property_t *propertyList = class_copyPropertyList([self class], &count);
    for (unsigned int k = 0; k < count; k++) {
        const char *propertyName = property_getName(propertyList[k]);
        NSLog(@"属性： %@", [NSString stringWithUTF8String:propertyName]);
    }
    free(propertyList);
    
    
    //方法
    Method *methodList = class_copyMethodList([self class], &count);
    for (unsigned int k = 0; k < count; k++) {
        Method method = methodList[k];
        NSLog(@"方法： %@", NSStringFromSelector(method_getName(method)));
    }
    free(methodList);
    
    //成员变量
    Ivar *ivarList = class_copyIvarList([self class], &count);
    for (unsigned int k = 0; k < count; k++) {
        const char *ivarName = ivar_getName(ivarList[k]);
        NSLog(@"成员变量 ： %@", [NSString stringWithUTF8String:ivarName]);
    }
    free(ivarList);
    
    //协议
    __unsafe_unretained Protocol **protocolList = class_copyProtocolList([self class], &count);
    for (unsigned int k = 0; k < count; k++) {
        const char *protocolName = protocol_getName(protocolList[k]);
        NSLog(@"协议： %@", [NSString stringWithUTF8String:protocolName]);
    }
    free(protocolList);
}


@end
